home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the 3D Game Programming Gurus / gurus.iso / DirectX / dx9sdkcp.exe / SDK (C++) / Bin / DXUtils / Visual Studio 6.0 Wizards / Source Code / Template / dxutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-12  |  36.6 KB  |  1,105 lines

  1. //-----------------------------------------------------------------------------
  2. // File: DXUtil.cpp
  3. //
  4. // Desc: Shortcut macros and functions for using DX objects
  5. //-----------------------------------------------------------------------------
  6. #ifndef STRICT
  7. #define STRICT
  8. #endif // !STRICT
  9. $$IF(DLG)
  10. #include "stdafx.h"
  11. $$ENDIF
  12. #include <windows.h>
  13. #include <mmsystem.h>
  14. #include <tchar.h>
  15. #include <stdio.h> 
  16. #include <stdarg.h>
  17. #include "DXUtil.h"
  18.  
  19.  
  20. #ifdef UNICODE
  21.     typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
  22. #else
  23.     typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd);
  24. #endif
  25.  
  26.  
  27. #ifndef UNDER_CE
  28. //-----------------------------------------------------------------------------
  29. // Name: DXUtil_GetDXSDKMediaPathCch()
  30. // Desc: Returns the DirectX SDK media path
  31. //       cchDest is the size in TCHARs of strDest.  Be careful not to 
  32. //       pass in sizeof(strDest) on UNICODE builds.
  33. //-----------------------------------------------------------------------------
  34. HRESULT DXUtil_GetDXSDKMediaPathCch( TCHAR* strDest, int cchDest )
  35. {
  36.     if( strDest == NULL || cchDest < 1 )
  37.         return E_INVALIDARG;
  38.  
  39.     lstrcpy( strDest, TEXT("") );
  40.  
  41.     // Open the appropriate registry key
  42.     HKEY  hKey;
  43.     LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  44.                                 _T("Software\\Microsoft\\DirectX SDK"),
  45.                                 0, KEY_READ, &hKey );
  46.     if( ERROR_SUCCESS != lResult )
  47.         return E_FAIL;
  48.  
  49.     DWORD dwType;
  50.     DWORD dwSize = cchDest * sizeof(TCHAR);
  51.     lResult = RegQueryValueEx( hKey, _T("DX9SDK Samples Path"), NULL,
  52.                               &dwType, (BYTE*)strDest, &dwSize );
  53.     strDest[cchDest-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small
  54.     RegCloseKey( hKey );
  55.  
  56.     if( ERROR_SUCCESS != lResult )
  57.         return E_FAIL;
  58.  
  59.     const TCHAR* strMedia = _T("\\Media\\");
  60.     if( lstrlen(strDest) + lstrlen(strMedia) < cchDest )
  61.         _tcscat( strDest, strMedia );
  62.     else
  63.         return E_INVALIDARG;
  64.  
  65.     return S_OK;
  66. }
  67. #endif // !UNDER_CE
  68.  
  69.  
  70.  
  71. #ifndef UNDER_CE
  72. //-----------------------------------------------------------------------------
  73. // Name: DXUtil_FindMediaFileCch()
  74. // Desc: Returns a valid path to a DXSDK media file
  75. //       cchDest is the size in TCHARs of strDestPath.  Be careful not to 
  76. //       pass in sizeof(strDest) on UNICODE builds.
  77. //-----------------------------------------------------------------------------
  78. HRESULT DXUtil_FindMediaFileCch( TCHAR* strDestPath, int cchDest, TCHAR* strFilename )
  79. {
  80.     HRESULT hr;
  81.     HANDLE file;
  82.     TCHAR* strShortNameTmp = NULL;
  83.     TCHAR strShortName[MAX_PATH];
  84.     int cchPath;
  85.  
  86.     if( NULL==strFilename || NULL==strDestPath || cchDest < 1 )
  87.         return E_INVALIDARG;
  88.  
  89.     lstrcpy( strDestPath, TEXT("") );
  90.     lstrcpy( strShortName, TEXT("") );
  91.  
  92.     // Build full path name from strFileName (strShortName will be just the leaf filename)
  93.     cchPath = GetFullPathName(strFilename, cchDest, strDestPath, &strShortNameTmp);
  94.     if ((cchPath == 0) || (cchDest <= cchPath))
  95.         return E_FAIL;
  96.     if( strShortNameTmp )
  97.         lstrcpyn( strShortName, strShortNameTmp, MAX_PATH );
  98.  
  99.     // first try to find the filename given a full path
  100.     file = CreateFile( strDestPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  101.                        OPEN_EXISTING, 0, NULL );
  102.     if( INVALID_HANDLE_VALUE != file )
  103.     {
  104.         CloseHandle( file );
  105.         return S_OK;
  106.     }
  107.     
  108.     // next try to find the filename in the current working directory (path stripped)
  109.     file = CreateFile( strShortName, GENERIC_READ, FILE_SHARE_READ, NULL, 
  110.                        OPEN_EXISTING, 0, NULL );
  111.     if( INVALID_HANDLE_VALUE != file )
  112.     {
  113.         _tcsncpy( strDestPath, strShortName, cchDest );
  114.         strDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
  115.         CloseHandle( file );
  116.         return S_OK;
  117.     }
  118.     
  119.     // last, check if the file exists in the media directory
  120.     if( FAILED( hr = DXUtil_GetDXSDKMediaPathCch( strDestPath, cchDest ) ) )
  121.         return hr;
  122.  
  123.     if( lstrlen(strDestPath) + lstrlen(strShortName) < cchDest )
  124.         lstrcat( strDestPath, strShortName );
  125.     else
  126.         return E_INVALIDARG;
  127.  
  128.     file = CreateFile( strDestPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  129.                        OPEN_EXISTING, 0, NULL );
  130.     if( INVALID_HANDLE_VALUE != file )
  131.     {
  132.         CloseHandle( file );
  133.         return S_OK;
  134.     }
  135.  
  136.     // On failure, just return the file as the path
  137.     _tcsncpy( strDestPath, strFilename, cchDest );
  138.     strDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
  139.     return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  140. }
  141. #endif // !UNDER_CE
  142.  
  143.  
  144.  
  145.  
  146. //-----------------------------------------------------------------------------
  147. // Name: DXUtil_ReadStringRegKeyCch()
  148. // Desc: Helper function to read a registry key string
  149. //       cchDest is the size in TCHARs of strDest.  Be careful not to 
  150. //       pass in sizeof(strDest) on UNICODE builds.
  151. //-----------------------------------------------------------------------------
  152. HRESULT DXUtil_ReadStringRegKeyCch( HKEY hKey, TCHAR* strRegName, TCHAR* strDest, 
  153.                                     DWORD cchDest, TCHAR* strDefault )
  154. {
  155.     DWORD dwType;
  156.     DWORD cbDest = cchDest * sizeof(TCHAR);
  157.  
  158.     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
  159.                                           (BYTE*)strDest, &cbDest ) )
  160.     {
  161.         _tcsncpy( strDest, strDefault, cchDest );
  162.         strDest[cchDest-1] = 0;
  163.  
  164.         if( dwType != REG_SZ )
  165.             return E_FAIL;
  166.  
  167.         return S_OK;
  168.     }
  169.  
  170.     return E_FAIL;
  171. }
  172.  
  173.  
  174.  
  175.  
  176. //-----------------------------------------------------------------------------
  177. // Name: DXUtil_WriteStringRegKey()
  178. // Desc: Helper function to write a registry key string
  179. //-----------------------------------------------------------------------------
  180. HRESULT DXUtil_WriteStringRegKey( HKEY hKey, TCHAR* strRegName,
  181.                                   TCHAR* strValue )
  182. {
  183.     if( NULL == strValue )
  184.         return E_INVALIDARG;
  185.         
  186.     DWORD cbValue = ((DWORD)_tcslen(strValue)+1) * sizeof(TCHAR);
  187.  
  188.     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_SZ, 
  189.                                         (BYTE*)strValue, cbValue ) )
  190.         return E_FAIL;
  191.  
  192.     return S_OK;
  193. }
  194.  
  195.  
  196.  
  197.  
  198. //-----------------------------------------------------------------------------
  199. // Name: DXUtil_ReadIntRegKey()
  200. // Desc: Helper function to read a registry key int
  201. //-----------------------------------------------------------------------------
  202. HRESULT DXUtil_ReadIntRegKey( HKEY hKey, TCHAR* strRegName, DWORD* pdwDest, 
  203.                               DWORD dwDefault )
  204. {
  205.     DWORD dwType;
  206.     DWORD dwLength = sizeof(DWORD);
  207.  
  208.     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
  209.                                           (BYTE*)pdwDest, &dwLength ) )
  210.     {
  211.         *pdwDest = dwDefault;
  212.         if( dwType != REG_DWORD )
  213.             return E_FAIL;
  214.  
  215.         return S_OK;
  216.     }
  217.  
  218.     return E_FAIL;
  219. }
  220.  
  221.  
  222.  
  223.  
  224. //-----------------------------------------------------------------------------
  225. // Name: DXUtil_WriteIntRegKey()
  226. // Desc: Helper function to write a registry key int
  227. //-----------------------------------------------------------------------------
  228. HRESULT DXUtil_WriteIntRegKey( HKEY hKey, TCHAR* strRegName, DWORD dwValue )
  229. {
  230.     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, 
  231.                                         (BYTE*)&dwValue, sizeof(DWORD) ) )
  232.         return E_FAIL;
  233.  
  234.     return S_OK;
  235. }
  236.  
  237.  
  238.  
  239.  
  240. //-----------------------------------------------------------------------------
  241. // Name: DXUtil_ReadBoolRegKey()
  242. // Desc: Helper function to read a registry key BOOL
  243. //-----------------------------------------------------------------------------
  244. HRESULT DXUtil_ReadBoolRegKey( HKEY hKey, TCHAR* strRegName, BOOL* pbDest, 
  245.                               BOOL bDefault )
  246. {
  247.     DWORD dwType;
  248.     DWORD dwLength = sizeof(BOOL);
  249.  
  250.     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
  251.                                           (BYTE*)pbDest, &dwLength ) )
  252.     {
  253.         *pbDest = bDefault;
  254.         if( dwType != REG_DWORD )
  255.             return E_FAIL;
  256.  
  257.         return S_OK;
  258.     }
  259.  
  260.     return E_FAIL;
  261. }
  262.  
  263.  
  264.  
  265.  
  266. //-----------------------------------------------------------------------------
  267. // Name: DXUtil_WriteBoolRegKey()
  268. // Desc: Helper function to write a registry key BOOL
  269. //-----------------------------------------------------------------------------
  270. HRESULT DXUtil_WriteBoolRegKey( HKEY hKey, TCHAR* strRegName, BOOL bValue )
  271. {
  272.     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, 
  273.                                         (BYTE*)&bValue, sizeof(BOOL) ) )
  274.         return E_FAIL;
  275.  
  276.     return S_OK;
  277. }
  278.  
  279.  
  280.  
  281.  
  282. //-----------------------------------------------------------------------------
  283. // Name: DXUtil_ReadGuidRegKey()
  284. // Desc: Helper function to read a registry key guid
  285. //-----------------------------------------------------------------------------
  286. HRESULT DXUtil_ReadGuidRegKey( HKEY hKey, TCHAR* strRegName, GUID* pGuidDest, 
  287.                                GUID& guidDefault )
  288. {
  289.     DWORD dwType;
  290.     DWORD dwLength = sizeof(GUID);
  291.  
  292.     if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
  293.                                           (LPBYTE) pGuidDest, &dwLength ) )
  294.     {
  295.         *pGuidDest = guidDefault;
  296.         if( dwType != REG_BINARY )
  297.             return E_FAIL;
  298.  
  299.         return S_OK;
  300.     }
  301.  
  302.     return E_FAIL;
  303. }
  304.  
  305.  
  306.  
  307.  
  308. //-----------------------------------------------------------------------------
  309. // Name: DXUtil_WriteGuidRegKey()
  310. // Desc: Helper function to write a registry key guid
  311. //-----------------------------------------------------------------------------
  312. HRESULT DXUtil_WriteGuidRegKey( HKEY hKey, TCHAR* strRegName, GUID guidValue )
  313. {
  314.     if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_BINARY, 
  315.                                         (BYTE*)&guidValue, sizeof(GUID) ) )
  316.         return E_FAIL;
  317.  
  318.     return S_OK;
  319. }
  320.  
  321.  
  322.  
  323.  
  324. //-----------------------------------------------------------------------------
  325. // Name: DXUtil_Timer()
  326. // Desc: Performs timer opertations. Use the following commands:
  327. //          TIMER_RESET           - to reset the timer
  328. //          TIMER_START           - to start the timer
  329. //          TIMER_STOP            - to stop (or pause) the timer
  330. //          TIMER_ADVANCE         - to advance the timer by 0.1 seconds
  331. //          TIMER_GETABSOLUTETIME - to get the absolute system time
  332. //          TIMER_GETAPPTIME      - to get the current time
  333. //          TIMER_GETELAPSEDTIME  - to get the time that elapsed between 
  334. //                                  TIMER_GETELAPSEDTIME calls
  335. //-----------------------------------------------------------------------------
  336. FLOAT __stdcall DXUtil_Timer( TIMER_COMMAND command )
  337. {
  338.     static BOOL     m_bTimerInitialized = FALSE;
  339.     static BOOL     m_bUsingQPF         = FALSE;
  340.     static BOOL     m_bTimerStopped     = TRUE;
  341.     static LONGLONG m_llQPFTicksPerSec  = 0;
  342.  
  343.     // Initialize the timer
  344.     if( FALSE == m_bTimerInitialized )
  345.     {
  346.         m_bTimerInitialized = TRUE;
  347.  
  348.         // Use QueryPerformanceFrequency() to get frequency of timer.  If QPF is
  349.         // not supported, we will timeGetTime() which returns milliseconds.
  350.         LARGE_INTEGER qwTicksPerSec;
  351.         m_bUsingQPF = QueryPerformanceFrequency( &qwTicksPerSec );
  352.         if( m_bUsingQPF )
  353.             m_llQPFTicksPerSec = qwTicksPerSec.QuadPart;
  354.     }
  355.  
  356.     if( m_bUsingQPF )
  357.     {
  358.         static LONGLONG m_llStopTime        = 0;
  359.         static LONGLONG m_llLastElapsedTime = 0;
  360.         static LONGLONG m_llBaseTime        = 0;
  361.         double fTime;
  362.         double fElapsedTime;
  363.         LARGE_INTEGER qwTime;
  364.         
  365.         // Get either the current time or the stop time, depending
  366.         // on whether we're stopped and what command was sent
  367.         if( m_llStopTime != 0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME)
  368.             qwTime.QuadPart = m_llStopTime;
  369.         else
  370.             QueryPerformanceCounter( &qwTime );
  371.  
  372.         // Return the elapsed time
  373.         if( command == TIMER_GETELAPSEDTIME )
  374.         {
  375.             fElapsedTime = (double) ( qwTime.QuadPart - m_llLastElapsedTime ) / (double) m_llQPFTicksPerSec;
  376.             m_llLastElapsedTime = qwTime.QuadPart;
  377.             return (FLOAT) fElapsedTime;
  378.         }
  379.     
  380.         // Return the current time
  381.         if( command == TIMER_GETAPPTIME )
  382.         {
  383.             double fAppTime = (double) ( qwTime.QuadPart - m_llBaseTime ) / (double) m_llQPFTicksPerSec;
  384.             return (FLOAT) fAppTime;
  385.         }
  386.     
  387.         // Reset the timer
  388.         if( command == TIMER_RESET )
  389.         {
  390.             m_llBaseTime        = qwTime.QuadPart;
  391.             m_llLastElapsedTime = qwTime.QuadPart;
  392.             m_llStopTime        = 0;
  393.             m_bTimerStopped     = FALSE;
  394.             return 0.0f;
  395.         }
  396.     
  397.         // Start the timer
  398.         if( command == TIMER_START )
  399.         {
  400.             if( m_bTimerStopped )
  401.                 m_llBaseTime += qwTime.QuadPart - m_llStopTime;
  402.             m_llStopTime = 0;
  403.             m_llLastElapsedTime = qwTime.QuadPart;
  404.             m_bTimerStopped = FALSE;
  405.             return 0.0f;
  406.         }
  407.     
  408.         // Stop the timer
  409.         if( command == TIMER_STOP )
  410.         {
  411.             if( !m_bTimerStopped )
  412.             {
  413.                 m_llStopTime = qwTime.QuadPart;
  414.                 m_llLastElapsedTime = qwTime.QuadPart;
  415.                 m_bTimerStopped = TRUE;
  416.             }
  417.             return 0.0f;
  418.         }
  419.     
  420.         // Advance the timer by 1/10th second
  421.         if( command == TIMER_ADVANCE )
  422.         {
  423.             m_llStopTime += m_llQPFTicksPerSec/10;
  424.             return 0.0f;
  425.         }
  426.  
  427.         if( command == TIMER_GETABSOLUTETIME )
  428.         {
  429.             fTime = qwTime.QuadPart / (double) m_llQPFTicksPerSec;
  430.             return (FLOAT) fTime;
  431.         }
  432.  
  433.         return -1.0f; // Invalid command specified
  434.     }
  435.     else
  436.     {
  437.         // Get the time using timeGetTime()
  438.         static double m_fLastElapsedTime  = 0.0;
  439.         static double m_fBaseTime         = 0.0;
  440.         static double m_fStopTime         = 0.0;
  441.         double fTime;
  442.         double fElapsedTime;
  443.         
  444.         // Get either the current time or the stop time, depending
  445.         // on whether we're stopped and what command was sent
  446.         if( m_fStopTime != 0.0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME)
  447.             fTime = m_fStopTime;
  448.         else
  449.             fTime = GETTIMESTAMP() * 0.001;
  450.     
  451.         // Return the elapsed time
  452.         if( command == TIMER_GETELAPSEDTIME )
  453.         {   
  454.             fElapsedTime = (double) (fTime - m_fLastElapsedTime);
  455.             m_fLastElapsedTime = fTime;
  456.             return (FLOAT) fElapsedTime;
  457.         }
  458.     
  459.         // Return the current time
  460.         if( command == TIMER_GETAPPTIME )
  461.         {
  462.             return (FLOAT) (fTime - m_fBaseTime);
  463.         }
  464.     
  465.         // Reset the timer
  466.         if( command == TIMER_RESET )
  467.         {
  468.             m_fBaseTime         = fTime;
  469.             m_fLastElapsedTime  = fTime;
  470.             m_fStopTime         = 0;
  471.             m_bTimerStopped     = FALSE;
  472.             return 0.0f;
  473.         }
  474.     
  475.         // Start the timer
  476.         if( command == TIMER_START )
  477.         {
  478.             if( m_bTimerStopped )
  479.                 m_fBaseTime += fTime - m_fStopTime;
  480.             m_fStopTime = 0.0f;
  481.             m_fLastElapsedTime  = fTime;
  482.             m_bTimerStopped = FALSE;
  483.             return 0.0f;
  484.         }
  485.     
  486.         // Stop the timer
  487.         if( command == TIMER_STOP )
  488.         {
  489.             if( !m_bTimerStopped )
  490.             {
  491.                 m_fStopTime = fTime;
  492.                 m_fLastElapsedTime  = fTime;
  493.                 m_bTimerStopped = TRUE;
  494.             }
  495.             return 0.0f;
  496.         }
  497.     
  498.         // Advance the timer by 1/10th second
  499.         if( command == TIMER_ADVANCE )
  500.         {
  501.             m_fStopTime += 0.1f;
  502.             return 0.0f;
  503.         }
  504.  
  505.         if( command == TIMER_GETABSOLUTETIME )
  506.         {
  507.             return (FLOAT) fTime;
  508.         }
  509.  
  510.         return -1.0f; // Invalid command specified
  511.     }
  512. }
  513.  
  514.  
  515.  
  516.  
  517. //-----------------------------------------------------------------------------
  518. // Name: DXUtil_ConvertAnsiStringToWideCch()
  519. // Desc: This is a UNICODE conversion utility to convert a CHAR string into a
  520. //       WCHAR string. 
  521. //       cchDestChar is the size in TCHARs of wstrDestination.  Be careful not to 
  522. //       pass in sizeof(strDest) 
  523. //-----------------------------------------------------------------------------
  524. HRESULT DXUtil_ConvertAnsiStringToWideCch( WCHAR* wstrDestination, const CHAR* strSource, 
  525.                                      int cchDestChar )
  526. {
  527.     if( wstrDestination==NULL || strSource==NULL || cchDestChar < 1 )
  528.         return E_INVALIDARG;
  529.  
  530.     int nResult = MultiByteToWideChar( CP_ACP, 0, strSource, -1, 
  531.                                        wstrDestination, cchDestChar );
  532.     wstrDestination[cchDestChar-1] = 0;
  533.     
  534.     if( nResult == 0 )
  535.         return E_FAIL;
  536.     return S_OK;
  537. }
  538.  
  539.  
  540.  
  541.  
  542. //-----------------------------------------------------------------------------
  543. // Name: DXUtil_ConvertWideStringToAnsi()
  544. // Desc: This is a UNICODE conversion utility to convert a WCHAR string into a
  545. //       CHAR string. 
  546. //       cchDestChar is the size in TCHARs of strDestination
  547. //-----------------------------------------------------------------------------
  548. HRESULT DXUtil_ConvertWideStringToAnsiCch( CHAR* strDestination, const WCHAR* wstrSource, 
  549.                                      int cchDestChar )
  550. {
  551.     if( strDestination==NULL || wstrSource==NULL || cchDestChar < 1 )
  552.         return E_INVALIDARG;
  553.  
  554.     int nResult = WideCharToMultiByte( CP_ACP, 0, wstrSource, -1, strDestination, 
  555.                                        cchDestChar*sizeof(CHAR), NULL, NULL );
  556.     strDestination[cchDestChar-1] = 0;
  557.     
  558.     if( nResult == 0 )
  559.         return E_FAIL;
  560.     return S_OK;
  561. }
  562.  
  563.  
  564.  
  565.  
  566. //-----------------------------------------------------------------------------
  567. // Name: DXUtil_ConvertGenericStringToAnsi()
  568. // Desc: This is a UNICODE conversion utility to convert a TCHAR string into a
  569. //       CHAR string. 
  570. //       cchDestChar is the size in TCHARs of strDestination
  571. //-----------------------------------------------------------------------------
  572. HRESULT DXUtil_ConvertGenericStringToAnsiCch( CHAR* strDestination, const TCHAR* tstrSource, 
  573.                                            int cchDestChar )
  574. {
  575.     if( strDestination==NULL || tstrSource==NULL || cchDestChar < 1 )
  576.         return E_INVALIDARG;
  577.  
  578. #ifdef _UNICODE
  579.     return DXUtil_ConvertWideStringToAnsiCch( strDestination, tstrSource, cchDestChar );
  580. #else
  581.     strncpy( strDestination, tstrSource, cchDestChar );
  582.     strDestination[cchDestChar-1] = '\0';
  583.     return S_OK;
  584. #endif   
  585. }
  586.  
  587.  
  588.  
  589.  
  590. //-----------------------------------------------------------------------------
  591. // Name: DXUtil_ConvertGenericStringToWide()
  592. // Desc: This is a UNICODE conversion utility to convert a TCHAR string into a
  593. //       WCHAR string. 
  594. //       cchDestChar is the size in TCHARs of wstrDestination.  Be careful not to 
  595. //       pass in sizeof(strDest) 
  596. //-----------------------------------------------------------------------------
  597. HRESULT DXUtil_ConvertGenericStringToWideCch( WCHAR* wstrDestination, const TCHAR* tstrSource, 
  598.                                            int cchDestChar )
  599. {
  600.     if( wstrDestination==NULL || tstrSource==NULL || cchDestChar < 1 )
  601.         return E_INVALIDARG;
  602.  
  603. #ifdef _UNICODE
  604.     wcsncpy( wstrDestination, tstrSource, cchDestChar );
  605.     wstrDestination[cchDestChar-1] = L'\0';
  606.     return S_OK;
  607. #else
  608.     return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, tstrSource, cchDestChar );
  609. #endif    
  610. }
  611.  
  612.  
  613.  
  614.  
  615. //-----------------------------------------------------------------------------
  616. // Name: DXUtil_ConvertAnsiStringToGeneric()
  617. // Desc: This is a UNICODE conversion utility to convert a CHAR string into a
  618. //       TCHAR string. 
  619. //       cchDestChar is the size in TCHARs of tstrDestination.  Be careful not to 
  620. //       pass in sizeof(strDest) on UNICODE builds
  621. //-----------------------------------------------------------------------------
  622. HRESULT DXUtil_ConvertAnsiStringToGenericCch( TCHAR* tstrDestination, const CHAR* strSource, 
  623.                                            int cchDestChar )
  624. {
  625.     if( tstrDestination==NULL || strSource==NULL || cchDestChar < 1 )
  626.         return E_INVALIDARG;
  627.         
  628. #ifdef _UNICODE
  629.     return DXUtil_ConvertAnsiStringToWideCch( tstrDestination, strSource, cchDestChar );
  630. #else
  631.     strncpy( tstrDestination, strSource, cchDestChar );
  632.     tstrDestination[cchDestChar-1] = '\0';
  633.     return S_OK;
  634. #endif    
  635. }
  636.  
  637.  
  638.  
  639.  
  640. //-----------------------------------------------------------------------------
  641. // Name: DXUtil_ConvertAnsiStringToGeneric()
  642. // Desc: This is a UNICODE conversion utility to convert a WCHAR string into a
  643. //       TCHAR string. 
  644. //       cchDestChar is the size in TCHARs of tstrDestination.  Be careful not to 
  645. //       pass in sizeof(strDest) on UNICODE builds
  646. //-----------------------------------------------------------------------------
  647. HRESULT DXUtil_ConvertWideStringToGenericCch( TCHAR* tstrDestination, const WCHAR* wstrSource, 
  648.                                            int cchDestChar )
  649. {
  650.     if( tstrDestination==NULL || wstrSource==NULL || cchDestChar < 1 )
  651.         return E_INVALIDARG;
  652.  
  653. #ifdef _UNICODE
  654.     wcsncpy( tstrDestination, wstrSource, cchDestChar );
  655.     tstrDestination[cchDestChar-1] = L'\0';    
  656.     return S_OK;
  657. #else
  658.     return DXUtil_ConvertWideStringToAnsiCch( tstrDestination, wstrSource, cchDestChar );
  659. #endif
  660. }
  661.  
  662.  
  663.  
  664.  
  665.  
  666. //-----------------------------------------------------------------------------
  667. // Name: DXUtil_LaunchReadme()
  668. // Desc: Finds and opens the readme.txt for this sample
  669. //-----------------------------------------------------------------------------
  670. VOID DXUtil_LaunchReadme( HWND hWnd, TCHAR* strLoc )
  671. {
  672.  
  673. #ifdef UNDER_CE
  674.     // This is not available on PocketPC
  675.     MessageBox( hWnd, TEXT("For operating instructions, please open the ")
  676.                       TEXT("readme.txt file included with the project."),
  677.                 TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK );
  678.  
  679.     return;
  680. #else 
  681.  
  682.     bool bSuccess = false;
  683.     bool bFound = false;
  684.     TCHAR strReadmePath[1024];
  685.     TCHAR strExeName[MAX_PATH];
  686.     TCHAR strExePath[MAX_PATH];
  687.     TCHAR strSamplePath[MAX_PATH];
  688.     TCHAR* strLastSlash = NULL;
  689.  
  690.     lstrcpy( strReadmePath, TEXT("") );
  691.     lstrcpy( strExePath, TEXT("") );
  692.     lstrcpy( strExeName, TEXT("") );
  693.     lstrcpy( strSamplePath, TEXT("") );
  694.  
  695.     // If the user provided a location for the readme, check there first.
  696.     if( strLoc )
  697.     {
  698.         HKEY  hKey;
  699.         LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  700.                                     _T("Software\\Microsoft\\DirectX SDK"),
  701.                                     0, KEY_READ, &hKey );
  702.         if( ERROR_SUCCESS == lResult )
  703.         {
  704.             DWORD dwType;
  705.             DWORD dwSize = MAX_PATH * sizeof(TCHAR);
  706.             lResult = RegQueryValueEx( hKey, _T("DX9SDK Samples Path"), NULL,
  707.                                       &dwType, (BYTE*)strSamplePath, &dwSize );
  708.             strSamplePath[MAX_PATH-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small
  709.             
  710.             if( ERROR_SUCCESS == lResult )
  711.             {
  712.                 _sntprintf( strReadmePath, 1023, TEXT("%s\\C++\\%s\\readme.txt"), 
  713.                             strSamplePath, strLoc );
  714.                 strReadmePath[1023] = 0;
  715.  
  716.                 if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  717.                     bFound = TRUE;
  718.             }
  719.         }
  720.  
  721.         RegCloseKey( hKey );
  722.     }
  723.  
  724.     // Get the exe name, and exe path
  725.     GetModuleFileName( NULL, strExePath, MAX_PATH );
  726.     strExePath[MAX_PATH-1]=0;
  727.  
  728.     strLastSlash = _tcsrchr( strExePath, TEXT('\\') );
  729.     if( strLastSlash )
  730.     {
  731.         _tcsncpy( strExeName, &strLastSlash[1], MAX_PATH );
  732.         strExeName[MAX_PATH-1]=0;
  733.  
  734.         // Chop the exe name from the exe path
  735.         *strLastSlash = 0;
  736.  
  737.         // Chop the .exe from the exe name
  738.         strLastSlash = _tcsrchr( strExeName, TEXT('.') );
  739.         if( strLastSlash )
  740.             *strLastSlash = 0;
  741.     }
  742.  
  743.     if( !bFound )
  744.     {
  745.         // Search in "%EXE_DIR%\..\%EXE_NAME%".  This matchs the DirectX SDK layout
  746.         _tcscpy( strReadmePath, strExePath );
  747.  
  748.         strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
  749.         if( strLastSlash )
  750.             *strLastSlash = 0;
  751.         lstrcat( strReadmePath, TEXT("\\") );
  752.         lstrcat( strReadmePath, strExeName );
  753.         lstrcat( strReadmePath, TEXT("\\readme.txt") );
  754.         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  755.             bFound = TRUE;
  756.     }
  757.  
  758.     if( !bFound )
  759.     {
  760.         // Search in "%EXE_DIR%\"
  761.         _tcscpy( strReadmePath, strExePath );
  762.         lstrcat( strReadmePath, TEXT("\\readme.txt") );
  763.         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  764.             bFound = TRUE;
  765.     }
  766.  
  767.     if( !bFound )
  768.     {
  769.         // Search in "%EXE_DIR%\.."
  770.         _tcscpy( strReadmePath, strExePath );
  771.         strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
  772.         if( strLastSlash )
  773.             *strLastSlash = 0;
  774.         lstrcat( strReadmePath, TEXT("\\readme.txt") );
  775.         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  776.             bFound = TRUE;
  777.     }
  778.  
  779.     if( !bFound )
  780.     {
  781.         // Search in "%EXE_DIR%\..\.."
  782.         _tcscpy( strReadmePath, strExePath );
  783.         strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
  784.         if( strLastSlash )
  785.             *strLastSlash = 0;
  786.         strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
  787.         if( strLastSlash )
  788.             *strLastSlash = 0;
  789.         lstrcat( strReadmePath, TEXT("\\readme.txt") );
  790.         if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
  791.             bFound = TRUE;
  792.     }
  793.  
  794.     if( bFound )
  795.     {
  796.         // GetProcAddress for ShellExecute, so we don't have to include shell32.lib 
  797.         // in every project that uses dxutil.cpp
  798.         LPShellExecute pShellExecute = NULL;
  799.         HINSTANCE hInstShell32 = LoadLibrary(TEXT("shell32.dll"));
  800.         if (hInstShell32 != NULL)
  801.         {
  802. #ifdef UNICODE
  803.             pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteW"));
  804. #else
  805.             pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteA"));
  806. #endif
  807.             if( pShellExecute != NULL )
  808.             {
  809.                 if( pShellExecute( hWnd, TEXT("open"), strReadmePath, NULL, NULL, SW_SHOW ) > (HINSTANCE) 32 )
  810.                     bSuccess = true;
  811.             }
  812.  
  813.             FreeLibrary(hInstShell32);
  814.         }
  815.     }
  816.  
  817.     if( !bSuccess )
  818.     {
  819.         // Tell the user that the readme couldn't be opened
  820.         MessageBox( hWnd, TEXT("Could not find readme.txt"), 
  821.                     TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK );
  822.     }
  823.  
  824. #endif // UNDER_CE
  825. }
  826.  
  827.  
  828.  
  829.  
  830.  
  831. //-----------------------------------------------------------------------------
  832. // Name: DXUtil_Trace()
  833. // Desc: Outputs to the debug stream a formatted string with a variable-
  834. //       argument list.
  835. //-----------------------------------------------------------------------------
  836. VOID DXUtil_Trace( TCHAR* strMsg, ... )
  837. {
  838. #if defined(DEBUG) | defined(_DEBUG)
  839.     TCHAR strBuffer[512];
  840.     
  841.     va_list args;
  842.     va_start(args, strMsg);
  843.     _vsntprintf( strBuffer, 512, strMsg, args );
  844.     va_end(args);
  845.  
  846.     OutputDebugString( strBuffer );
  847. #else
  848.     UNREFERENCED_PARAMETER(strMsg);
  849. #endif
  850. }
  851.  
  852.  
  853.  
  854.  
  855. //-----------------------------------------------------------------------------
  856. // Name: DXUtil_ConvertStringToGUID()
  857. // Desc: Converts a string to a GUID
  858. //-----------------------------------------------------------------------------
  859. HRESULT DXUtil_ConvertStringToGUID( const TCHAR* strSrc, GUID* pGuidDest )
  860. {
  861.     UINT aiTmp[10];
  862.  
  863.     if( _stscanf( strSrc, TEXT("{%8X-%4X-%4X-%2X%2X-%2X%2X%2X%2X%2X%2X}"),
  864.                     &pGuidDest->Data1, 
  865.                     &aiTmp[0], &aiTmp[1], 
  866.                     &aiTmp[2], &aiTmp[3],
  867.                     &aiTmp[4], &aiTmp[5],
  868.                     &aiTmp[6], &aiTmp[7],
  869.                     &aiTmp[8], &aiTmp[9] ) != 11 )
  870.     {
  871.         ZeroMemory( pGuidDest, sizeof(GUID) );
  872.         return E_FAIL;
  873.     }
  874.     else
  875.     {
  876.         pGuidDest->Data2       = (USHORT) aiTmp[0];
  877.         pGuidDest->Data3       = (USHORT) aiTmp[1];
  878.         pGuidDest->Data4[0]    = (BYTE) aiTmp[2];
  879.         pGuidDest->Data4[1]    = (BYTE) aiTmp[3];
  880.         pGuidDest->Data4[2]    = (BYTE) aiTmp[4];
  881.         pGuidDest->Data4[3]    = (BYTE) aiTmp[5];
  882.         pGuidDest->Data4[4]    = (BYTE) aiTmp[6];
  883.         pGuidDest->Data4[5]    = (BYTE) aiTmp[7];
  884.         pGuidDest->Data4[6]    = (BYTE) aiTmp[8];
  885.         pGuidDest->Data4[7]    = (BYTE) aiTmp[9];
  886.         return S_OK;
  887.     }
  888. }
  889.  
  890.  
  891.  
  892.  
  893. //-----------------------------------------------------------------------------
  894. // Name: DXUtil_ConvertGUIDToStringCch()
  895. // Desc: Converts a GUID to a string 
  896. //       cchDestChar is the size in TCHARs of strDest.  Be careful not to 
  897. //       pass in sizeof(strDest) on UNICODE builds
  898. //-----------------------------------------------------------------------------
  899. HRESULT DXUtil_ConvertGUIDToStringCch( const GUID* pGuidSrc, TCHAR* strDest, int cchDestChar )
  900. {
  901.     int nResult = _sntprintf( strDest, cchDestChar, TEXT("{%0.8X-%0.4X-%0.4X-%0.2X%0.2X-%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X}"),
  902.                pGuidSrc->Data1, pGuidSrc->Data2, pGuidSrc->Data3,
  903.                pGuidSrc->Data4[0], pGuidSrc->Data4[1],
  904.                pGuidSrc->Data4[2], pGuidSrc->Data4[3],
  905.                pGuidSrc->Data4[4], pGuidSrc->Data4[5],
  906.                pGuidSrc->Data4[6], pGuidSrc->Data4[7] );
  907.  
  908.     if( nResult < 0 )
  909.         return E_FAIL;
  910.     return S_OK;
  911. }
  912.  
  913.  
  914.  
  915.  
  916. //-----------------------------------------------------------------------------
  917. // Name: CArrayList constructor
  918. // Desc: 
  919. //-----------------------------------------------------------------------------
  920. CArrayList::CArrayList( ArrayListType Type, UINT BytesPerEntry )
  921. {
  922.     if( Type == AL_REFERENCE )
  923.         BytesPerEntry = sizeof(void*);
  924.     m_ArrayListType = Type;
  925.     m_pData = NULL;
  926.     m_BytesPerEntry = BytesPerEntry;
  927.     m_NumEntries = 0;
  928.     m_NumEntriesAllocated = 0;
  929. }
  930.  
  931.  
  932.  
  933. //-----------------------------------------------------------------------------
  934. // Name: CArrayList destructor
  935. // Desc: 
  936. //-----------------------------------------------------------------------------
  937. CArrayList::~CArrayList( void )
  938. {
  939.     if( m_pData != NULL )
  940.         delete[] m_pData;
  941. }
  942.  
  943.  
  944.  
  945.  
  946. //-----------------------------------------------------------------------------
  947. // Name: CArrayList::Add
  948. // Desc: Adds pEntry to the list.
  949. //-----------------------------------------------------------------------------
  950. HRESULT CArrayList::Add( void* pEntry )
  951. {
  952.     if( m_BytesPerEntry == 0 )
  953.         return E_FAIL;
  954.     if( m_pData == NULL || m_NumEntries + 1 > m_NumEntriesAllocated )
  955.     {
  956.         void* pDataNew;
  957.         UINT NumEntriesAllocatedNew;
  958.         if( m_NumEntriesAllocated == 0 )
  959.             NumEntriesAllocatedNew = 16;
  960.         else
  961.             NumEntriesAllocatedNew = m_NumEntriesAllocated * 2;
  962.         pDataNew = new BYTE[NumEntriesAllocatedNew * m_BytesPerEntry];
  963.         if( pDataNew == NULL )
  964.             return E_OUTOFMEMORY;
  965.         if( m_pData != NULL )
  966.         {
  967.             CopyMemory( pDataNew, m_pData, m_NumEntries * m_BytesPerEntry );
  968.             delete[] m_pData;
  969.         }
  970.         m_pData = pDataNew;
  971.         m_NumEntriesAllocated = NumEntriesAllocatedNew;
  972.     }
  973.  
  974.     if( m_ArrayListType == AL_VALUE )
  975.         CopyMemory( (BYTE*)m_pData + (m_NumEntries * m_BytesPerEntry), pEntry, m_BytesPerEntry );
  976.     else
  977.         *(((void**)m_pData) + m_NumEntries) = pEntry;
  978.     m_NumEntries++;
  979.  
  980.     return S_OK;
  981. }
  982.  
  983.  
  984.  
  985.  
  986. //-----------------------------------------------------------------------------
  987. // Name: CArrayList::Remove
  988. // Desc: Remove the item at Entry in the list, and collapse the array. 
  989. //-----------------------------------------------------------------------------
  990. void CArrayList::Remove( UINT Entry )
  991. {
  992.     // Decrement count
  993.     m_NumEntries--;
  994.  
  995.     // Find the entry address
  996.     BYTE* pData = (BYTE*)m_pData + (Entry * m_BytesPerEntry);
  997.  
  998.     // Collapse the array
  999.     MoveMemory( pData, pData + m_BytesPerEntry, ( m_NumEntries - Entry ) * m_BytesPerEntry );
  1000. }
  1001.  
  1002.  
  1003.  
  1004.  
  1005. //-----------------------------------------------------------------------------
  1006. // Name: CArrayList::GetPtr
  1007. // Desc: Returns a pointer to the Entry'th entry in the list.
  1008. //-----------------------------------------------------------------------------
  1009. void* CArrayList::GetPtr( UINT Entry )
  1010. {
  1011.     if( m_ArrayListType == AL_VALUE )
  1012.         return (BYTE*)m_pData + (Entry * m_BytesPerEntry);
  1013.     else
  1014.         return *(((void**)m_pData) + Entry);
  1015. }
  1016.  
  1017.  
  1018.  
  1019.  
  1020. //-----------------------------------------------------------------------------
  1021. // Name: CArrayList::Contains
  1022. // Desc: Returns whether the list contains an entry identical to the 
  1023. //       specified entry data.
  1024. //-----------------------------------------------------------------------------
  1025. bool CArrayList::Contains( void* pEntryData )
  1026. {
  1027.     for( UINT iEntry = 0; iEntry < m_NumEntries; iEntry++ )
  1028.     {
  1029.         if( m_ArrayListType == AL_VALUE )
  1030.         {
  1031.             if( memcmp( GetPtr(iEntry), pEntryData, m_BytesPerEntry ) == 0 )
  1032.                 return true;
  1033.         }
  1034.         else
  1035.         {
  1036.             if( GetPtr(iEntry) == pEntryData )
  1037.                 return true;
  1038.         }
  1039.     }
  1040.     return false;
  1041. }
  1042.  
  1043.  
  1044.  
  1045.  
  1046. //-----------------------------------------------------------------------------
  1047. // Name: BYTE helper functions
  1048. // Desc: cchDestChar is the size in BYTEs of strDest.  Be careful not to 
  1049. //       pass use sizeof() if the strDest is a string pointer.  
  1050. //       eg.
  1051. //       TCHAR* sz = new TCHAR[100]; // sizeof(sz)  == 4
  1052. //       TCHAR sz2[100];             // sizeof(sz2) == 200
  1053. //-----------------------------------------------------------------------------
  1054. HRESULT DXUtil_ConvertAnsiStringToWideCb( WCHAR* wstrDestination, const CHAR* strSource, int cbDestChar )
  1055. {
  1056.     return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, strSource, cbDestChar / sizeof(WCHAR) );
  1057. }
  1058.  
  1059. HRESULT DXUtil_ConvertWideStringToAnsiCb( CHAR* strDestination, const WCHAR* wstrSource, int cbDestChar )
  1060. {
  1061.     return DXUtil_ConvertWideStringToAnsiCch( strDestination, wstrSource, cbDestChar / sizeof(CHAR) );
  1062. }
  1063.  
  1064. HRESULT DXUtil_ConvertGenericStringToAnsiCb( CHAR* strDestination, const TCHAR* tstrSource, int cbDestChar )
  1065. {
  1066.     return DXUtil_ConvertGenericStringToAnsiCch( strDestination, tstrSource, cbDestChar / sizeof(CHAR) );
  1067. }
  1068.  
  1069. HRESULT DXUtil_ConvertGenericStringToWideCb( WCHAR* wstrDestination, const TCHAR* tstrSource, int cbDestChar )
  1070. {
  1071.     return DXUtil_ConvertGenericStringToWideCch( wstrDestination, tstrSource, cbDestChar / sizeof(WCHAR) );
  1072. }
  1073.  
  1074. HRESULT DXUtil_ConvertAnsiStringToGenericCb( TCHAR* tstrDestination, const CHAR* strSource, int cbDestChar )
  1075. {
  1076.     return DXUtil_ConvertAnsiStringToGenericCch( tstrDestination, strSource, cbDestChar / sizeof(TCHAR) );
  1077. }
  1078.  
  1079. HRESULT DXUtil_ConvertWideStringToGenericCb( TCHAR* tstrDestination, const WCHAR* wstrSource, int cbDestChar )
  1080. {
  1081.     return DXUtil_ConvertWideStringToGenericCch( tstrDestination, wstrSource, cbDestChar / sizeof(TCHAR) );
  1082. }
  1083.  
  1084. HRESULT DXUtil_ReadStringRegKeyCb( HKEY hKey, TCHAR* strRegName, TCHAR* strDest, DWORD cbDest, TCHAR* strDefault )
  1085. {
  1086.     return DXUtil_ReadStringRegKeyCch( hKey, strRegName, strDest, cbDest / sizeof(TCHAR), strDefault );
  1087. }
  1088.  
  1089. HRESULT DXUtil_ConvertGUIDToStringCb( const GUID* pGuidSrc, TCHAR* strDest, int cbDestChar )
  1090. {
  1091.     return DXUtil_ConvertGUIDToStringCch( pGuidSrc, strDest, cbDestChar / sizeof(TCHAR) );
  1092. }
  1093.  
  1094. #ifndef UNDER_CE
  1095. HRESULT DXUtil_GetDXSDKMediaPathCb( TCHAR* szDest, int cbDest )
  1096. {
  1097.     return DXUtil_GetDXSDKMediaPathCch( szDest, cbDest / sizeof(TCHAR) );
  1098. }
  1099.  
  1100. HRESULT DXUtil_FindMediaFileCb( TCHAR* szDestPath, int cbDest, TCHAR* strFilename )
  1101. {
  1102.     return DXUtil_FindMediaFileCch( szDestPath, cbDest / sizeof(TCHAR), strFilename );
  1103. }
  1104. #endif // !UNDER_CE
  1105.